home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / XPK / Source / xpkmaster / open.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-04  |  12.8 KB  |  457 lines

  1. #ifndef XPKMASTER_OPEN_C
  2. #define XPKMASTER_OPEN_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        open.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: open.c 1.7 (31.03.97)
  9.     Author:        SDI
  10.     Distribution:    PD
  11.     Description:    Opening and initialisation routines for XPK files
  12.  
  13.  1.0   06.10.96 : first real version
  14.  1.1   28.10.96 : reincluded A4 support
  15.  1.2   03.03.97 : added Prefs, corrected length recognition
  16.  1.3   07.03.97 : fixed prefs handling, new features
  17.  1.4   09.03.97 : added DEBUG statement
  18.  1.5   28.03.97 : auto decrunch password
  19.  1.6   29.03.97 : fixed prefs stuff, moved getinlen into hooks
  20.  1.7   31.03.97 : changed the password stuff
  21. */
  22.  
  23. #include <exec/types.h>
  24. #include <dos/dos.h>
  25. #include <xpk/xpkprefs.h>
  26. #include <exec/memory.h>
  27. #include <pragma/exec_lib.h>
  28. #include <pragma/dos_lib.h>
  29. #include <pragma/xpkmaster_lib.h>
  30. #include "xpkmaster.h"
  31. #include "xpk_strings.h"
  32.  
  33. struct XpkInfo DONTInfo = { 1,0,0,1,"DONT","Copy",
  34. 0, 0x55534552, XPKIF_PK_CHUNK|XPKIF_UP_CHUNK, 50000, 10, 50000,
  35. 0,0,0,0,100,0,0 /* Mode */,0,0,0,0,0,0};
  36.  
  37. static LONG GetPrefsPacker(struct XpkBuffer *xbuf);
  38. static LONG GetPassword(struct XpkBuffer *xbuf, struct TagItem *tags);
  39. static struct XpkTypeData *BufRecog(ULONG, struct XpkBuffer *,
  40.   struct XpkPrefsSemaphore *);
  41.  
  42. #define ROW_OF_MINUS    0x2d2d2d2d    /* '----' */
  43. #define PP_COOKIE    0x50503230    /* 'PP20' */
  44.  
  45. LONG __asm xpkopen(register __a0 struct XpkBuffer **xbufp,
  46. register __a1 struct TagItem *tags, register __d2 ULONG examine A4PROTO)
  47. {
  48.   struct Library     *XpkSubBase;
  49.   struct XpkBuffer     *xbuf;
  50.   struct XpkStreamHeader *globhdr;
  51.   struct XpkFib         *fib;
  52.   LONG bytesread;    /* used to be able to reset after a short read */
  53.  
  54. #if defined(DEBUG) && defined(SUPPORT_A4)
  55.   DebugRunTime("xpkopen: A4 = %ld", a4);
  56. #elif defined (DEBUG)
  57.   DebugRunTime("xpkopen");
  58. #endif
  59.  
  60.   *xbufp = 0;
  61.   if(!(xbuf = initxbuf()))
  62.   {
  63.     parseerrortags(tags);
  64.     return XPKERR_NOMEM;
  65.   }
  66.  
  67. #ifdef SUPPORT_A4
  68.   xbuf->xb_regA4 = a4;
  69. #endif
  70.  
  71.   globhdr = &xbuf->xb_Headers.h_Glob;
  72.   fib = &xbuf->xb_Fib;
  73.  
  74.   if(parsebuftags(xbuf, tags, 0))
  75.     goto Abort;
  76.  
  77.   *xbufp = xbuf;
  78.   if(xbuf->xb_Flags & XMF_PACKING)
  79.     return xpkopenwrite(xbufp, tags);
  80.  
  81.   if(!hookread(xbuf, XIO_READ, globhdr, 4))
  82.   {    /* Read first longword only */
  83.     bytesread = xbuf->xb_RMsg.xmm_Size;
  84.     if(xbuf->xb_Result != XPKERR_TRUNCATED)
  85.       goto Abort;
  86.     /* else handle now as uncompressed file */
  87.   }
  88.   else
  89.     bytesread = 4;
  90.  
  91.   /**************************** Standard XPK file *********************/
  92.   if(globhdr->xsh_Pack == XPK_COOKIE)
  93.   {    /* Standard XPK packed files */
  94.     UWORD exthlen = 0;        /* size of extended header if present */
  95.  
  96.     xbuf->xb_Format = XPKMODE_UPSTD;
  97.  
  98.     /* Read rest of the global header */
  99.     if(!hookread(xbuf, XIO_READ, (STRPTR) globhdr + 4, sizeof(struct XpkStreamHeader) - 4))
  100.       goto Abort;
  101.  
  102.     if(hchecksum((STRPTR) globhdr, sizeof(struct XpkStreamHeader)))
  103.     {
  104.       xbuf->xb_Result = XPKERR_CHECKSUM;
  105.       goto Abort;
  106.     }
  107.  
  108.     if(!examine && globhdr->xsh_Flags & XPKSTREAMF_PASSWORD &&
  109.     !xbuf->xb_Password)
  110.     {
  111.       if((xbuf->xb_Result = GetPassword(xbuf, tags)))
  112.         goto Abort;
  113.     }
  114.  
  115.     if(globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS)
  116.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrLong);
  117.     else
  118.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrWord);
  119.  
  120.     if(globhdr->xsh_Flags & XPKSTREAMF_EXTHEADER)
  121.     {
  122.       if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD)))
  123.     goto Abort;
  124.       if(!hookread(xbuf, XIO_READ, NULL, exthlen))
  125.     goto Abort;
  126.       exthlen += sizeof(UWORD);    /* for unwinding while XpkExamine */
  127.     }
  128.  
  129.     if(!hookread(xbuf, XIO_READ, &xbuf->xb_Headers.h_Loc,
  130.     xbuf->xb_Headers.h_LocSize))    /* first lochdr */
  131.       goto Abort;
  132.  
  133.     xbuf->xb_Fib.xf_CCur = sizeof(struct XpkStreamHeader);
  134.     updatefib(xbuf);
  135.     xbuf->xb_InLen = xbuf->xb_Fib.xf_CLen;
  136.  
  137.     if(!(xbuf->xb_SubBase = XpkSubBase = opensub(xbuf, globhdr->xsh_Type)))
  138.       goto Abort;
  139.  
  140.     if(globhdr->xsh_SubVrs > xbuf->xb_SubInfo->xi_LibVersion)
  141.     {
  142.       xbuf->xb_Result = XPKERR_OLDSUBLIB;
  143.       goto Abort;
  144.     }
  145.  
  146.     xbuf->xb_ULen = globhdr->xsh_ULen;
  147.     xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_UnpackMsg ?
  148.       xbuf->xb_SubInfo->xi_UnpackMsg : strings[TXT_UNPACKING_UPPER];
  149.     xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  150.     xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_UnpackedMsg ?
  151.       xbuf->xb_SubInfo->xi_UnpackedMsg : strings[TXT_UNPACKED];
  152.  
  153.     if(globhdr->xsh_Flags & XPKSTREAMF_PASSWORD)
  154.       xbuf->xb_Fib.xf_Flags |= XPKFLAGS_PASSWORD;
  155.  
  156.     if(examine && !hookread(xbuf, XIO_SEEK, 0,
  157.     -(sizeof(struct XpkStreamHeader) + xbuf->xb_Headers.h_LocSize+exthlen)))
  158.       goto Abort;
  159.  
  160.     goto Exit;
  161.   }
  162.  
  163.   if(!hookread(xbuf, XIO_SEEK, 0, -bytesread))
  164.     goto Abort;
  165.  
  166.   if(xbuf->xb_InLen == -1)
  167.   {
  168.     if(!hookread(xbuf, XIO_TOTSIZE, 0, 0))    /* get input length */
  169.       return xbuf->xb_Result;
  170.     else if(xbuf->xb_RMsg.xmm_Size)
  171.       xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
  172.   }
  173.  
  174. #ifdef USE_POWERPACKER
  175.   /***************************** PowerPacker file ***********************/
  176.   if(globhdr->xsh_Pack == PP_COOKIE)
  177.   {
  178.     struct Library *PPBase;
  179.     LONG outsize;
  180.  
  181.     xbuf->xb_Format = XPKMODE_UPPP;
  182.  
  183.     if(!hookread(xbuf, XIO_SEEK, 0, xbuf->xb_InLen - 4))
  184.       goto Abort;                /* 4 Bytes before EOF */
  185.     if(!hookread(xbuf, XIO_READ, &outsize, 4))
  186.       goto Abort;
  187.     if(!hookread(xbuf, XIO_SEEK, 0, - (xbuf->xb_InLen - 4) - (examine<<2)))
  188.       goto Abort;    /* back to start when examine, else 4 bytes later */
  189.  
  190.     outsize >>= 8;
  191.  
  192. #ifdef DEBUG
  193.     DebugRunTime("xpkopen: PP, InLen %ld, OutLen %ld", xbuf->xb_InLen,
  194.     outsize);
  195. #endif
  196.  
  197.     fib->xf_Type = XPKTYPE_PACKED;
  198.     fib->xf_CLen = xbuf->xb_InLen;
  199.     fib->xf_ULen = outsize;
  200.     fib->xf_NLen = outsize + XPK_MARGIN;
  201.     fib->xf_ID = PP_COOKIE;
  202.     percentages(fib);
  203.  
  204.     if(examine)
  205.       goto Exit;
  206.  
  207.     xbuf->xb_Prog.xp_Activity = strings[TXT_UNPACKING_UPPER];
  208.     xbuf->xb_Prog.xp_PackerName = "PowerPacker";
  209.     xbuf->xb_LastMsg = strings[TXT_UNPACKED];
  210.     xbuf->xb_ULen = outsize;
  211.  
  212.     if(!(PPBase = OpenLibrary ("powerpacker.library", 0)))
  213.     {
  214.       xbuf->xb_Result = XPKERR_MISSINGLIB;
  215.       goto Abort;
  216.     }
  217.     xbuf->xb_SubBase = PPBase;
  218.  
  219.     goto Exit;
  220.   }
  221. #endif /* USE_POWERPACKER */
  222.  
  223.   /**************************** Uncompressed file *************************/
  224.   if(examine || xbuf->xb_Flags & XMF_PASSTHRU)        /* Unpacked */
  225.   {
  226.     xbuf->xb_Format = XPKMODE_UPUP;
  227.  
  228.     fib->xf_Type = XPKTYPE_UNPACKED;
  229.     fib->xf_CLen = xbuf->xb_InLen;
  230.     fib->xf_ULen = xbuf->xb_InLen;
  231.     fib->xf_NLen = Min(CHUNKSIZE, xbuf->xb_InLen) + XPK_MARGIN;
  232.     fib->xf_ID = ROW_OF_MINUS;
  233.  
  234.     xbuf->xb_Prog.xp_Activity = strings[TXT_READING];
  235.     xbuf->xb_Prog.xp_PackerName = "MASTER";
  236.     xbuf->xb_LastMsg = strings[TXT_READ];
  237.     xbuf->xb_ULen = xbuf->xb_InLen;
  238.  
  239.     xbuf->xb_Result = XPKERR_OK;    /* if != 0 is was XPKERR_TRUNCATED */
  240.  
  241.     goto Exit;
  242.   }
  243.  
  244.   xbuf->xb_Result = XPKERR_NOTPACKED;    /* Can't unpack, can't passthru */
  245.  
  246. Abort:
  247.   *xbufp = 0;
  248.   return XpkClose((struct XpkFib *) xbuf);
  249.  
  250. Exit:
  251.   *xbufp = xbuf;
  252.   return XPKERR_OK;
  253. }
  254.  
  255. /****************************** Open for packing **************************/
  256. LONG xpkopenwrite(struct XpkBuffer **xbufp, struct TagItem *tags)
  257. {
  258.   struct XpkBuffer        *xbuf        = *xbufp;
  259.   struct XpkStreamHeader    *globhdr    = &xbuf->xb_Headers.h_Glob;
  260.   struct Library        *XpkSubBase;
  261.   LONG                 res;
  262.  
  263.   xbuf->xb_Format = XPKMODE_PKSTD;
  264.  
  265.   if(xbuf->xb_InLen == -1)
  266.   {
  267.     if(!hookread(xbuf, XIO_TOTSIZE, 0, 0))    /* get input length */
  268.       return xbuf->xb_Result;
  269.     else if(xbuf->xb_RMsg.xmm_Size)
  270.       xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
  271.   }
  272.  
  273.   if(!(XpkSubBase = xbuf->xb_SubBase) &&  /* Do we know the sublib? */
  274.   GetPrefsPacker(xbuf))
  275.   { /* no sublib and no prefs packer finder */
  276.     xbuf->xb_Result = XPKERR_BADPARAMS;
  277.     goto Abort;
  278.   }
  279.  
  280.   xbuf->xb_MinChunk = xbuf->xb_SubInfo->xi_MinPkInChunk;
  281.  
  282.   if(xbuf->xb_Password && !(xbuf->xb_SubInfo->xi_Flags & XPKIF_ENCRYPTION))
  283.   {
  284.     xbuf->xb_Result = XPKERR_NOCRYPT;
  285.     goto Abort;
  286.   }
  287.  
  288.   if(!xbuf->xb_Password && (xbuf->xb_SubInfo->xi_Flags & XPKIF_NEEDPASSWD))
  289.   { /* automatic password requester */
  290.     if((xbuf->xb_Result = GetPassword(xbuf, tags)))
  291.       goto Abort;
  292.   }
  293.  
  294.   if(!(xbuf->xb_Flags & XMF_LOSSYOK) &&
  295.   xbuf->xb_SubInfo->xi_Flags & XPKIF_LOSSY)
  296.   {
  297.     xbuf->xb_Result = XPKERR_LOSSY;
  298.     goto Abort;
  299.   }
  300.  
  301.   if(xbuf->xb_PackingMode > 100)    /* Is packing mode valid? */
  302.     xbuf->xb_PackingMode = 100;        /* Use max */
  303.  
  304.   if(!hookwrite(xbuf, XIO_TOTSIZE, 0, ROUNDLONG
  305.   (xbuf->xb_InLen + (xbuf->xb_InLen >> 5)) + (XPK_MARGIN<<1)))
  306.     goto Abort;
  307.  
  308.   /*********************** Find the chunk size *********************/
  309.   if((xbuf->xb_ChunkSize == 0) &&
  310.   ((xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_DefPkInChunk) == 0))
  311.     xbuf->xb_ChunkSize = DEFAULTCHUNKSIZE;
  312.   if(xbuf->xb_ChunkSize < xbuf->xb_SubInfo->xi_MinPkInChunk)
  313.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MinPkInChunk;
  314.   if((xbuf->xb_SubInfo->xi_MaxPkInChunk) &&
  315.   (xbuf->xb_ChunkSize > xbuf->xb_SubInfo->xi_MaxPkInChunk))
  316.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MaxPkInChunk;
  317.  
  318.   /******************* Prepare global header *********************/
  319.   globhdr->xsh_Pack = 0;        /* Initialize the global header */
  320.   globhdr->xsh_Type = xbuf->xb_SubID;
  321.  
  322.   if(xbuf->xb_ChunkSize > 65000)
  323.     globhdr->xsh_Flags |= XPKSTREAMF_LONGHEADERS;
  324.   if(xbuf->xb_Password)
  325.     globhdr->xsh_Flags |= XPKSTREAMF_PASSWORD;
  326.  
  327.   xbuf->xb_Headers.h_LocSize = globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS
  328.     ? sizeof (struct XpkChunkHdrLong)
  329.     : sizeof (struct XpkChunkHdrWord);
  330.  
  331.   memset(globhdr->xsh_Initial, 0xff, 16);    /* Read first 16 bytes */
  332.  
  333.   xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_PackMsg ?
  334.   xbuf->xb_SubInfo->xi_PackMsg : strings[TXT_PACKING_UPPER];
  335.   xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  336.   xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_PackedMsg ?
  337.   xbuf->xb_SubInfo->xi_PackedMsg : strings[TXT_PACKED];
  338.  
  339. Abort:
  340.   xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
  341.   xbuf->xb_ChunkSize);
  342.  
  343.   if((res = xbuf->xb_Result))
  344.     res = XpkClose((struct XpkFib *) xbuf);
  345.  
  346.   return res;
  347. }
  348.  
  349. typedef struct XpkTypeData * __asm (*RecogFunc) (register __a0 STRPTR,
  350.   register __a1 STRPTR, register __a2 STRPTR, register __d0 ULONG,
  351.   register __d1 ULONG);
  352.  
  353. static LONG GetPrefsPacker(struct XpkBuffer *xbuf)
  354. {
  355.   LONG ret = XPKERR_UNKNOWN;
  356.   struct XpkPrefsSemaphore *sem;
  357.   ULONG bufsize;
  358.   struct XpkTypeData *td = 0;
  359.  
  360.   if((xbuf->xb_Flags & XMF_NOPREFS) || !(sem = GetPrefsSem()))
  361.     return XPKERR_NOFUNC;
  362.  
  363.   bufsize = Min(xbuf->xb_InLen, sem->xps_RecogSize);
  364.  
  365.   if(sem->xps_RecogFunc && (td = BufRecog(bufsize, xbuf, sem)) ==
  366.   (struct XpkTypeData *) 0xFFFFFFFF)
  367.     td = BufRecog(xbuf->xb_InLen, xbuf, sem);
  368.  
  369.   if(!td || td == (struct XpkTypeData *) 0xFFFFFFFF)
  370.     td = sem->xps_MainPrefs ? sem->xps_MainPrefs->xmp_DefaultType : 0;
  371.  
  372.   if(td)
  373.   {
  374.     if(td->xtd_Flags & XTD_NoPack)
  375.     {
  376.       xbuf->xb_Flags |= XMF_NOPACK;
  377.       xbuf->xb_SubInfo = &DONTInfo;
  378.       ret = XPKERR_OK;
  379.     }
  380.     else if(!(td->xtd_Flags & XTD_ReturnError))
  381.     {
  382.       struct Library *XpkSubBase;
  383.       struct XpkInfo *subinfo;
  384.  
  385.       if((XpkSubBase = opensub(xbuf, td->xtd_StdID)))
  386.       {
  387.     ret = XPKERR_OK;
  388.         subinfo = XpksPackerInfo();
  389.  
  390.         xbuf->xb_ChunkSize = td->xtd_ChunkSize;
  391.         xbuf->xb_PackingMode = ( td->xtd_Mode ? td->xtd_Mode :
  392.           subinfo->xi_DefMode);
  393. //    if(!(xbuf->xb_Password) && td->xtd_Password && 
  394. //    (xbuf->xb_PasswordSize = strlen(td->xtd_Password)))
  395. //    {
  396. //      /* we need a buffer including end byte! --> ++size */
  397. //      if(!(xbuf->xb_Password = (STRPTR)
  398. //      AllocMem(++xbuf->xb_PasswordSize, MEMF_PUBLIC)))
  399. //        ret = XPKERR_NOMEM;
  400. //        else
  401. //      {
  402. //        xbuf->Flags |= XMF_OWNPASSWORD;
  403. //        CopyMem(td->xtd_Password, xbuf->xb_Password, xbuf->xb_PasswordSize);
  404. //      }
  405. //    }
  406.       }
  407.     }
  408.   }
  409.  
  410.   if(td->xtd_Memory && td->xtd_MemorySize)
  411.     FreeMem(td->xtd_Memory, td->xtd_MemorySize);
  412.  
  413.   ReleaseSemaphore((struct SignalSemaphore *) sem);
  414.   return ret;
  415. }
  416.  
  417. static LONG GetPassword(struct XpkBuffer *xbuf, struct TagItem *tags)
  418. {
  419.  if(xbuf->xb_Flags & XMF_AUTOPASSWD)
  420.  {
  421.    if(!(xbuf->xb_Password = (STRPTR) AllocMem(AUTO_PASS_SIZE, MEMF_PUBLIC)))
  422.      return XPKERR_NOMEM;
  423.    xbuf->xb_PasswordSize = AUTO_PASS_SIZE;
  424.    xbuf->xb_Flags |= XMF_OWNPASSWORD; /* must be freed later */
  425.  
  426.    if((xbuf->xb_Result = XpkPassRequestTags(XPK_PasswordBuf,
  427.    xbuf->xb_Password, XPK_PassBufSize, xbuf->xb_PasswordSize, TAG_MORE,
  428.    tags, TAG_DONE)))
  429.      return xbuf->xb_Result;
  430.    else
  431.    {
  432. #ifdef DEBUG
  433.      DebugRunTime("GetPassword: %s", xbuf->xb_Password);
  434. #endif
  435.      return XPKERR_OK;
  436.    }
  437.  }
  438.  return XPKERR_NEEDPASSWD;
  439. }
  440.  
  441. static struct XpkTypeData *BufRecog(ULONG bufsize, struct XpkBuffer *xbuf,
  442. struct XpkPrefsSemaphore *sem)
  443. {
  444.   STRPTR bufptr;
  445.   struct XpkTypeData *ret = 0;
  446.  
  447.   if((bufptr = hookread(xbuf, XIO_READ, 0, bufsize)))
  448.   {
  449.     ret = (((RecogFunc) sem->xps_RecogFunc) (bufptr, xbuf->xb_InName,
  450.     xbuf->xb_Prog.xp_FileName, bufsize, xbuf->xb_InLen));
  451.     hookread(xbuf, XIO_SEEK, 0, -bufsize);
  452.   }
  453.   return ret;
  454. }
  455.  
  456. #endif /* XPKMASTER_OPEN_C */
  457.